/*
	brief: 时间相关

*/

#pragma once
#include "../typedef.h"
#include "../singleton.h"
#include "su_timeUtil.h"
#include <time.h>
#include <vector>
#include <map>

namespace su
{
	//使用方法：用定时器每秒调用SysTime::Ins().Refresh()，其他时间不刷新。
	// 好处：1 比每次调用刷新效率高一点。 2函数运行过程中，SysTime::Ins()不会发生变化。避免时间变化引起的bug
	//使用例子：
	/*
		main_loop()
		{
			SysTime::Ins().Refresh();刷新当前系统时间
			const tm &t = SysTime::Ins().getTm();
		}

	*/
	class SysTime : public Singleton<SysTime>
	{
        friend class Singleton<SysTime>;
        SysTime();

	private:
		time_t   m_sec=0; //秒时间戳
		time_t   m_ms=0; //毫秒时间戳
		tm       m_tm;
		time_t   m_offset=0;

	public:
		static uint32_t GetCurTimeZone();//值为 +- 12 
        //para1: int y,  年   
        //para2: int m,  月
		static int GetDaysInMonth(int y, int m);

        //是闰年
		static bool IsLeapYear(int y);

		//获取time_t所在天的零时
		static time_t GetCurDayStart(time_t sec);
		//获取time_t所在周的第一天的零时, 失败返回0
		static time_t GetCurWeekStart(time_t sec);
		//获取time_t所在月的第一天的零时, 失败返回0
		static time_t GetCurMonStart(time_t sec);
		//获取time_t所在年的第一天的零时, 失败返回0
		static time_t GetCurYearStart(time_t sec);

		//!将用"%Y-%m-%d-%H-%M-%S"表示的时间转换成time_t
		static bool TimeStrToTime_t(const char* szTimeString, time_t& ret_time);
		//!将用"%Y-%m-%d-%H-%M-%S"表示的时间转换成tm表示的结构
		static bool TimeStringToTm(const char* szTimeString, tm& ret_tm);
		//!将用tTime表示的时间转换成用"%Y-%m-%d %H-%M-%S"表示
		static bool TimeToTimeStr(time_t t, std::string &str);
	public:
		//刷新当前日历时间
		void Refresh();
		//返回utc时间戳秒数
        inline time_t Sec() const{return m_sec;};
		//返回时间戳ms
		time_t Ms();
		//返回当前日历格式
		const tm &CurTm() const;
		//返回用"%Y-%m-%d %H-%M-%S"表示
        std::string GetTimeStr() const;

		//返回当前月有多少天
		int GetDaysInMonth() const;
		bool IsLeapYear() const;

        //调试用
        /////////////////////////////////////////
        //设置系统时间的偏移。 往未来偏移，不能往过去偏移。 比如设置1，表示获取系统时间==真实时间+1秒
		//@para isForcePast , true表示强制设置时间回到过去。//注意：仅测试用，时间回到过去，会很容易产生无法修复的BUG。
        bool SetTimeOffset(time_t offset, bool isForcePast=false);
		//注意：仅测试用，时间回到过去，会很容易产生无法修复的BUG。
		void ClearOffsetForTest();
        //加秒偏移
        void AddTimerOffset(time_t offset);
        //将格式"%Y-%m-%d-%H-%M-%S"表示的时间 设置为当前时间
		//数字必须为4位或者2位
		//@para isForcePast , true表示强制设置时间回到过去。//注意：仅测试用，时间回到过去，会很容易产生无法修复的BUG。
        bool SetTimeByStr(const char *pTime, bool isForcePast = false);
        //加月偏移
        void AddMonthOffset(unsigned int month);
        //加年偏移
        void AddYearOffset(unsigned int year);
        /////////////////////////////////////////

	};

	extern SysTime& gSysTime; //main执行前别用
}//namespace su